#
# Copyright (C) 2011
#
# Brick Yang <printfxxx@163.com>
#
# This program is free software. You can redistribute it and/or
# modify it as you like.
#

##
# File		gcc.mk
# Brief		GCC toolchain support.
#

ifeq ($(EXTMF_SEG),V)

ifneq ($(origin CC),environment)
CC = $(CROSS_COMPILE)gcc
endif
ifneq ($(origin AR),environment)
AR = $(CROSS_COMPILE)ar
endif
ifneq ($(origin LD),environment)
LD = $(CROSS_COMPILE)ld
endif
ifneq ($(origin NM),environment)
NM = $(CROSS_COMPILE)nm
endif
ifneq ($(origin OBJDUMP),environment)
OBJDUMP = $(CROSS_COMPILE)objdump
endif
ifneq ($(origin OBJCOPY),environment)
OBJCOPY = $(CROSS_COMPILE)objcopy
endif
ifneq ($(origin STRIP),environment)
STRIP = $(CROSS_COMPILE)strip
endif

export CC AR LD CFLAGS CFLAGS-y LDFLAGS LDFLAGS-y

endif	# ifeq ($(EXTMF_SEG),V)

ifeq ($(EXTR_SEG),V)

# Build out
define do_out
$(strip $(CC) $(1) -o $(2) $(3) -Wl,-Map=$(2)$(SFX_MAP))
endef
# Build obj
define do_cc
$(strip $(CC) -c $(1) -o $(2) $(3))
endef
# Relink obj
define do_robj
$(strip $(LD) -r $(1) -o $(2))
endef
# Build static library
define do_slib
$(strip $(AR) rc $(2) $(1))
endef
# Build share library
define do_dlib
$(strip $(CC) -fPIC -shared $(1) -o $(2))
endef
# Generate obj list
define do_olst
$(strip for f in $(1); do echo $$f; done > $(2) || ($(RM) $(2); false))
endef
# Rule for generate depend
define rule_cc_dep
sinclude $(2)$(SFX_D)
_$(2)_deps = $$(wildcard $$($(2)_deps))

$(2)$(SFX_D): $(1) $$(if $$(filter-out $$(_$(2)_deps),$$($(2)_deps)),FORCE,$$(_$(2)_deps))
	$(CC) $$< -M -MT $(2)_deps $(3) | sed -e '1s|:| =|' > $$@; \
	[ "$$$${PIPESTATUS[*]}" == "0 0" ] || ($(RM) $$@; $(call err,GEN,$$(@:$(bdir)%=%)); false)
endef
# Get objs in dirs
define join_dirs_olst
$(strip for d in $(1); do sed -e "s|^|$$d|" $$d/$(bdir)$(OLST); done)
endef
# Wrapper for build out
define do_out_wrapper
$(call do_out,$(objs_$(1)) `$(call join_dirs_olst,$(dirs_$(1)))`,$(2),$(_ldflags) $(ldflags_$(1)))
endef
# Wrapper for build robj
define do_robj_wrapper
$(call do_robj,$(objs_$(1)) `$(call join_dirs_olst,$(dirs_$(1)))`,$(2))
endef
# Wrapper for build slib
define do_slib_wrapper
$(call do_slib,$(objs_$(1)) `$(call join_dirs_olst,$(dirs_$(1)))`,$(2))
endef
# Wrapper for build dlib
define do_dlib_wrapper
$(call do_dlib,$(objs_$(1)) `$(call join_dirs_olst,$(dirs_$(1)))`,$(2))
endef
# Copy out file to optdir
define copy_out_to_opt
$(call copy_to_opt,$$(bdir),$(1),$(1:%$(SFX_OUT)=%))
endef
# Copy slib file to optdir
define copy_slib_to_opt
$(call copy_to_opt,$$(bdir),$(1),$(1))
endef
# Copy dlib file to optdir
define copy_dlib_to_opt
$(call copy_to_opt,$$(bdir),$(1),$(1))
endef
# Rule for install out
define install_out
$(call install,$$(bdir),$(1),$$(DESTDIR)/$$(bindir)/,$(1:%$(SFX_OUT)=%),0755)
endef
# Rule for install slib
define install_slib
$(call install,$$(bdir),$(1),$$(DESTDIR)/$$(libdir)/,$(1),0644)
endef
# Rule for install dlib
define install_dlib
$(call install,$$(bdir),$(1),$$(DESTDIR)/$$(libdir)/,$(1),0755)
endef
# Rule for install hdr
define install_hdr
$(call install,,$(1),$$(DESTDIR)/$$(includedir)/,$(1),0644)
endef

SFX_C	= .c
SFX_ASM = .S
SFX_CXX = .cpp
SFX_O	= .o
SFX_OUT = .out
SFX_A	= .a
SFX_D	= .d
SFX_SO	= .so
SFX_MAP = .map
SFX_LDS = .ld
SFX_CMD = .cmd

OUT  = $(filter %$(SFX_OUT),$(MOD))
ROBJ = $(filter %$(SFX_O),$(MOD))
SLIB = $(filter %$(SFX_A),$(MOD))
DLIB = $(filter %$(SFX_SO),$(MOD))
OBJ  = $(filter %$(SFX_O),$(TGT))
OLST = objs

cflags  = $(CFLAGS) $(CFLAGS-y)
_cflags = $(cflags) $(cflags-y)

ldflags  = $(LDFLAGS) $(LDFLAGS-y)
_ldflags = $(ldflags) $(ldflags-y)

endif	# ifeq ($(EXTR_SEG),V)

ifeq ($(EXTR_SEG),R)

$(foreach f,$(OUT) $(ROBJ) $(SLIB) $(DLIB),$(eval objs_$(f) = $(tgts_$(f):%=$(bdir)%)))
$(foreach f,$(OUT) $(ROBJ) $(SLIB) $(DLIB),$(eval $(bdir)$(f): $(dirs_$(f):%=%$(bdir)$(OLST))))

$(OUT:%=$(bdir)%$(SFX_CMD)): $(bdir)%$(SFX_CMD): FORCE
	$(call cmd_change_chk,$(call do_out_wrapper,$*,$(bdir)$*),$@)

$(ROBJ:%=$(bdir)%$(SFX_CMD)): $(bdir)%$(SFX_CMD): FORCE
	$(call cmd_change_chk,$(call do_robj_wrapper,$*,$(bdir)$*),$@)

$(SLIB:%=$(bdir)%$(SFX_CMD)): $(bdir)%$(SFX_CMD): FORCE
	$(call cmd_change_chk,$(call do_slib_wrapper,$*,$(bdir)$*),$@)

$(DLIB:%=$(bdir)%$(SFX_CMD)): $(bdir)%$(SFX_CMD): FORCE
	$(call cmd_change_chk,$(call do_dlib_wrapper,$*,$(bdir)$*),$@)

$(OUT:%=$(bdir)%): $(bdir)%: $(bdir)%$(SFX_CMD)
	$(call msg,LD,$*)
	$(call do_out_wrapper,$*,$@)

$(ROBJ:%=$(bdir)%): $(bdir)%: $(bdir)%$(SFX_CMD)
	$(call msg,LD,$*)
	$(call do_robj_wrapper,$*,$@)

$(SLIB:%=$(bdir)%): $(bdir)%: $(bdir)%$(SFX_CMD)
	$(call msg,AR,$*)
	$(call do_slib_wrapper,$*,$@)

$(DLIB:%=$(bdir)%): $(bdir)%: $(bdir)%$(SFX_CMD)
	$(call msg,LD,$*)
	$(call do_dlib_wrapper,$*,$@)

$(DIR:%=%$(bdir)$(OLST)): %/$(bdir)$(OLST): build-%

$(bdir)$(OLST)$(SFX_CMD): FORCE
	$(call cmd_change_chk,$(OBJ) `$(call join_dirs_olst,$(DIR))`,$@)

$(bdir)$(OLST): $(OBJ:%=$(bdir)%) $(DIR:%=%$(bdir)$(OLST)) $(bdir)$(OLST)$(SFX_CMD)
	$(call do_olst,$(OBJ:%=$(bdir)%) `$(call join_dirs_olst,$(DIR))`,$@)

all: $(bdir)$(OLST)

endif	# ifeq ($(EXTR_SEG),R)
